home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / em-xmkit.zip / TOOLKIT.TXT < prev   
Text File  |  1990-01-30  |  61KB  |  1,702 lines

  1.  
  2. The
  3. EMS TOOLKIT
  4. for C developers
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16. Copyright (c) 1989 Intel Corporation.  All rights reserved.
  17. Intel Corporation, 5200 NE Elam Young Parkway, Hillsboro, OR  97124
  18.  
  19.  
  20. First Edition            December, 1989
  21.  
  22.  
  23. DISCLAIMER
  24. Intel Corporation assumes no responsibility for errors that may appear in
  25. this manual.  Nor does Intel make any commitment to update the
  26. information contained in this manual.
  27.  
  28. Intel and Above are trademarks of Intel Corporation.
  29.  
  30.  
  31.  
  32.  
  33. LIMITED WARRANTY
  34. Intel Corporation excludes any and all implied warranties, including 
  35. warranties of merchantability and fitness for a particular purpose. Intel 
  36. makes no warranty of representation, either express or implied, with 
  37. respect to this software, its quality, performance, merchantability, or 
  38. fitness for a particular purpose.  Intel shall not have any liability for 
  39. special, incidental, or consequential damages arising out of or resulting 
  40. from the use or modification of this software. This software is provided as 
  41. is.
  42.  
  43.  
  44. USE OF PROGRAM PRODUCT You may use the Program Product on any one IBM or 
  45. compatible personal computer, and copy the Object Code into any 
  46. machine-readable form for your use of the Program Product; You may modify 
  47. the Program Product material and/or merge or incorporate it into any 
  48. general use software program of your development except for a utility 
  49. program of similar nature to the Program Product.  You may freely reproduce 
  50. any such program of your development; however, the merged or incorporated 
  51. part of the Program Product will continue to be subject to all other 
  52. provisions of this agreement.
  53.  
  54.  
  55.  
  56. CONTENTS
  57.  
  58.  
  59. CHAPTER 1.  GETTING STARTED
  60. How to use this book      1-2
  61. What's on the disks?      1-3
  62. Which library should I use?    1-5
  63. Requirements    1-7
  64. Installing the software   1-7
  65.  
  66. CHAPTER 2.  MEMLIB:  LIBRARY FOR C DEVELOPERS
  67. Compiling and linking MEMLIB   2-3
  68. Suggested sequence for using MEMLIB functions      2-4
  69. MEMLIB functions list     2-5 -- 2-31
  70.  
  71. CHAPTER 3.  EMMLIB:  LIBRARY FOR ASSEMBLY LANGUAGE AND C DEVELOPERS
  72. EMMLIB functions grouped by operation    3-3
  73. EMMLIB functions in alphabetical order   3-7
  74.  
  75. APPENDIX A.  EXAMPLE PROGRAM
  76.  
  77. APPENDIX B.  ERROR MESSAGES
  78.  
  79. APPENDIX C.  TECHNICAL INFORMATION ABOUT MEMLIB
  80. How MEMLIB provides access to expanded memory      C-1
  81. How MEMLIB keeps track of expanded memory     C-2
  82. How MEMLIB allocates expanded memory     C-2
  83. Algorithms      C-4
  84.  
  85.  
  86.  
  87. Chapter 1
  88. GETTING STARTED
  89.  
  90. This manual describes the toolkit for the Lotus-Intel-Microsoft Expanded 
  91. Memory Specification (EMS).  The toolkit offers  experienced Microsoft C 
  92. developers a quick and easy way to use expanded memory in their application 
  93. programs.
  94.  
  95. If you are writing programs in some other Microsoft language (Fortran, 
  96. Pascal, etc.), you may still be able to use the toolkit.  Read the 
  97. mixed-language programming section in the Microsoft manual to find out how 
  98. tomake calls to C from your language.
  99.  
  100. The toolkit includes the following libraries:
  101.  
  102. MEMLIB    A set of C functions that perform the "housekeeping"
  103.           necessary to access and store data in expanded memory.  When you
  104.           use MEMLIB, you won't need to worry about page frame size, 
  105.           16K-byte boundaries, or interfacing with an assembly language 
  106.           device driver.  See Chapter 2.
  107.  
  108. EMMLIB    A set of C-callable assembly language functions that call
  109.           the EMS driver directly.  See Chapter 3.
  110.  
  111. These libraries allow you to use the full functionality of EMS without
  112. spending countless hours writing assembly language programs.
  113.  
  114. This manual supplements the Lotus-Intel-Microsoft Expanded Memory
  115. Specification manual (also referred to as the EMS manual).  The LIM
  116. specification defines the software interface between an application
  117. program and the expanded memory used by the program.
  118.  
  119. How to use this book
  120. --------------------
  121. This manual explains the features and operation of the EMS Toolkit
  122. libraries.  Once you are familiar with the libraries and how to use
  123. them, you can use this book as a quick reference for function names,
  124. parameters, and error messages.
  125.  
  126. Here's what you'll find in each chapter of the manual: Chapter 1 -- Getting 
  127. Started:   This is the chapter you're reading now.  Besides introducing you 
  128. to the EMS Toolkit, this chapter lists the contents of the Intel diskettes, 
  129. offers suggestions for which library to use, and tells you how to install 
  130. the software.
  131.  
  132. Chapter 2 -- MEMLIB: Library for C Developers     This chapter describes 
  133. how the MEMLIB library works, how to write code to use MEMLIB, and how to 
  134. compile and link MEMLIB.  The last section (which makes up the bulk of this 
  135. chapter) describes each of the MEMLIB functions in detail.
  136.  
  137. Chapter 3 -- EMMLIB:  Library for Assembly Language and C Developers 
  138. Chapter 3 describes the EMMLIB library and how it works, and describes how 
  139. to compile and link EMMLIB.  This chapter also includes lists of EMMLIB 
  140. functions, and tells you how to get more information about each one.
  141.  
  142. Appendix A -- Example Progra:  This short example program
  143. demonstrates how to use MEMLIB to store and access data in expanded memory.
  144.  
  145. Appendix B -- Error Messages:  This appendix lists the error messages
  146. you may incur from MEMLIB, and suggests corrective actions.
  147.  
  148. Appendix C -- Technical Information About MEMLIB:  This appendix explains 
  149. the more technical aspects of how MEMLIB allocates and frees expanded 
  150. memory.  You don't need to know this information to use MEMLIB.
  151.  
  152. What's on the disks?
  153. --------------------
  154. The EMS Toolkit package includes four diskettes.  You'll need disks 1, 2 
  155. and 3 to use either of the toolkit libraries.  If you are an assembly 
  156. language developer and want to use expanded memory to execute code, you may 
  157. want to use disk 4.  Disk 4 contains examples for assembly language 
  158. programmers only.  (You don't need disk 4 to use MEMLIB or EMMLIB.)
  159.  
  160. The Intel EMS Toolkit diskettes contain the following files:
  161.  
  162.  Disk 1
  163. Filename            Description
  164.  MEMLIB.C            MEMLIB source code (functions)
  165.  MEMLIB.H            MEMLIB include file (function prototypes)
  166.  MEMINTRL.C          MEMLIB source code (internal MEMLIB utilities)
  167.  ERRORS.H            MEMLIB error messages
  168.  EMMLIB.LIB          EMM large-model library of C interface routines
  169.  EMMLIB.H            EMMLIB include file
  170.  
  171.  Disk 2
  172. Filename            Description
  173.  SAMPLE.C            Short sample program using MEMLIB functions
  174.  SAMPLE.MAK          "make" file for use with SAMPLE.C program
  175.  ROLODEX.C           More detailed sample program using MEMLIB and EMMLIB
  176.  ROLODEX.H           Header file for use with ROLODEX.C
  177.  ROLODEX.DAT         Data file for ROLODEX.C
  178.  ROLODEX.MAK         "make" file for use with ROLODEX.C program
  179.  EMMLIB   <DIR>      Directory containing EMMLIB function files
  180.  
  181.  Disk 3
  182. Filename            Description
  183.  EMMLIB   <DIR>      Directory containing the rest of the EMMLIB function
  184.                      files and other EMMLIB support files
  185.  
  186.  Disk 4
  187. Filename            Description
  188.  LOADCODE.ASM        Sample assembly language program that demonstrates how
  189.                      to execute code from expanded memory
  190.  HELLO.ASM           Sample code the LOADCODE.ASM will execute
  191.  LOADCODE.MAK        "make" file for LOADCODE.ASM
  192.  
  193.  
  194. Which library should I use?
  195. ---------------------------
  196. The way in which your application will use expanded memory determines
  197. which library you should use.
  198. o    If you are writing code in C and you want to store data in
  199.      expanded memory, you can use MEMLIB; it offers routines to do this 
  200.      quickly and easily.
  201. o    If you understand the Lotus-Intel-Microsoft Expanded Memory
  202.      Specification and want to make expanded memory calls directly from C,
  203.      you must use EMMLIB.  For example, if you want to use named handles for
  204.      the blocks of expanded memory you allocate, you need to use EMMLIB.
  205. o    If you want to use expanded memory for more complex uses such as
  206.      executing code, you must write your program in assembly language and
  207.      make EMS function calls directly.
  208.  
  209. Requirements
  210. ------------
  211. The functions in the EMS Toolkit libraries assume a few things about
  212. your computer's environment.
  213. +
  214. o    Both MEMLIB and EMMLIB assume that Microsoft C version 5.1 and its
  215.      "include" files are available on your system.
  216. o    MEMLIB assumes that you are using a C "large-memory-model."  EMMLIB
  217.      allows you to use any size memory model.
  218. o    The sample "make" files assume that the Microsoft utility MAKE.EXE
  219.      is available; that the source code, header files, and EMMLIB.LIB are
  220.      in one directory; and that the EMMLIB function files are in a 
  221.      subdirectory named \EMMLIB.  Intel recommends that you install the 
  222.      MEMLIB files and your application's source code in the same 
  223.      subdirectory.
  224.  
  225.  
  226. Installing the software
  227. -----------------------
  228. The following sequence is the way we suggest you install the EMS
  229. Toolkit software.  For this example, suppose the application source code is
  230. kept a subdirectory named \APP.
  231. 1    Insert Intel Toolkit diskette 1 into drive A.
  232.  
  233. 2    At the DOS prompt, type the following:
  234.           XCOPY  A:\*.*  C:\APP  /s
  235.  
  236. 3    Repeat the first two steps with diskettes 2 and 3.
  237.  
  238. This command will copy the contents of the Intel disks to the \APP
  239. directory on drive C.
  240.  
  241. /s  means that all files in subdirectories below A:\ will be copied,
  242. and will keep the same directory structure.  (If you'd like more
  243. information about the XCOPY command, refer to a DOS manual.)
  244.  
  245.  
  246.  
  247. Chapter 2
  248. MEMLIB:  LIBRARY FOR C DEVELOPERS
  249.  
  250.  
  251. MEMLIB is a set of functions that allow developers to manage expanded
  252. memory similar to the way they manage conventional memory with C.
  253. MEMLIB functions look and act like some of the more familiar C functions
  254. (malloc and free, for example).
  255.  
  256. MEMLIB's internal structure does the "housekeeping" necessary to access and 
  257. store data in expanded memory.  When you use MEMLIB, you won't need to 
  258. worry about page frame size, 16K-byte boundaries, or interfacing with an 
  259. assembly language device driver.
  260.  
  261. MEMLIB lets you allocate and access any size block of memory up to 64K
  262. bytes.  It tracks available free memory, and uses a "best fit"
  263. algorithm to allocate new blocks.
  264.  
  265. When you use MEMLIB, you just make a few C calls, and the libraries do
  266. the rest.
  267. Your application makes a call to MEMLIB, and MEMLIB in turn calls
  268. the EMMLIB library to access expanded memory.  EMMLIB then translates
  269. the C calls into assembly language, and passes the calls on to the EMS
  270. driver.
  271.  
  272.  
  273. Compiling and linking MEMLIB
  274. ----------------------------
  275. Because MEMLIB uses EMMLIB calls to perform its functions, you must
  276. link and compile both libraries when you use MEMLIB.  (The toolkit includes
  277. a previously made EMMLIB.LIB file to use with MEMLIB.)  You can compile
  278. and link either with "make" (a Microsoft C utility) or manually.
  279.  
  280. Using the "make" file
  281. ---------------------
  282. The easiest way to compile and link a number of interdependent modules
  283. is to use a "make" file.  A "make" file lists all of the modules and
  284. their dependencies in a single file.
  285.  
  286. A "make" file for a program called "SAMPLE" to use MEMLIB should
  287. contain the following lines.
  288.  
  289. (contents of the file sample.mak)
  290. memlib.obj: memlib.c memlib.h errors.h emmlib.h
  291.             CL /C /AL memlib.c
  292.  
  293. sample.obj: sample.c memlib.h errors.h
  294.             CL /C /AL sample.c
  295.  
  296. sample.exe: sample.obj memlib.obj
  297.             link sample memlib,,, emmlib.lib
  298.  
  299. To use the "make" file, type the following line at the DOS prompt:
  300.                 make sample.mak
  301.  
  302. If you change any file, just run the "make" file again to recompile
  303. and relink.
  304.  
  305.  
  306. Compile and link manually
  307. -------------------------
  308. Use the following command to compile the MEMLIB library:
  309.                  CL  /C /AL memlib.c
  310.  
  311. Use the following command to link MEMLIB to a program called "SAMPLE":
  312.                  LINK sample memlib, sample, nul, emmlib.lib
  313.  
  314.  
  315. Suggested sequence for using MEMLIB functions
  316. ---------------------------------------------
  317. MEMLIB functions provide a convenient way for your application to
  318. store data in expanded memory.  To use expanded memory (and MEMLIB) most
  319. effectively, your application should follow this sequence of actions:
  320.  
  321.  1.  Allocate memory     efmalloc allocates a block of expanded memory
  322.                          and returns a token (a block ID) to the application.
  323.  
  324.  2.  Access memory       seteptrs uses the token returned by efmalloc to
  325.                          access the blocks you allocated.  Also set1eptr, 
  326.                          set2eptrs, set3eptrs.
  327.  
  328.  3.  Free memory         effree frees previously allocated blocks of memory.
  329.                          Also effreeall. 
  330.  
  331. The other MEMLIB functions are provided for more specialized uses.
  332. You don't need to use them to store data in expanded memory.
  333.  
  334. **CAUTION**  Be sure to check the error codes that MEMLIB returns.  If
  335.              you try to allocate and use expanded memory when EMM isn't 
  336.              installed, you may lose data or overwrite some other area of 
  337.              memory.  To learn more about MEMLIB's error codes, read 
  338.              Appendix B.
  339.  
  340. The next section describes all of the MEMLIB functions in detail. Each 
  341. description includes the purpose of the function, the calling sequence to 
  342. use, and a short example program.
  343.  
  344. The functions are listed in alphabetical order for easy reference. Below is 
  345. a complete list of the functions grouped according to the operations they 
  346. perform.  To learn about a particular function, turn to the specified page.
  347.  
  348.  
  349.   Function               Page
  350. Allocating Memory         
  351.   efmalloc               2-10
  352.  
  353. Accessing Memory
  354.   seteptrs               2-24
  355.   set1eptr               2-28
  356.   set2eptrs              2-30
  357.   set3eptrs              2-32
  358.  
  359. Freeing Memory
  360.   effree                 2-6
  361.   effreeall              2-8
  362.  
  363. Other
  364.   ememavl                2-12
  365.   ememmax                2-14
  366.   emsize                 2-16
  367.   push_context           2-21
  368.   pop_context            2-18
  369.  
  370. This is all you need to begin using MEMLIB to get expanded memory for your 
  371. application program.  If you would like more detailed information about how 
  372. MEMLIB works, read Appendix C, Technical Information about MEMLIB.
  373.  
  374.  
  375. EFFREE
  376. ------
  377.  
  378. PURPOSE
  379. The effree function frees a block of memory that efmalloc had allocated.  
  380. Effree is analogous to the standard C function free.
  381.  
  382. **CAUTION**  The expanded memory manager (MEMLIB) is NOT a part of DOS.
  383.              MEMLIB will not automatically free your allocated blocks when
  384.              you exit your application.  Your application should free all
  385.              blocks during any kind of exit, including <CTL><BREAK> or 
  386.              other error conditions.  (See Function 6, effreeall.)
  387.          
  388. CALLING SEQUENCE
  389. unsigned int status;
  390. status = effree (token);
  391.  
  392.        unsigned int  token    The token that efmalloc returned when it 
  393.                               allocated that block of memory. (input)
  394.  
  395. STATUS
  396. PASSED (zero)           The block is now free.
  397. error (non-zero value)  See Appendix B for descriptions of error codes.
  398.  
  399. EXAMPLE
  400. #include "memlib.h"
  401. #include "errors.h"
  402.  
  403. unsigned int token;
  404. unsigned int status;
  405.  
  406. status = efmalloc (100, &token);
  407. if (status != PASSED)
  408.     /* error condition */
  409. else
  410.     /* continue normal code */
  411.     ...
  412. status = effree (token);
  413. if (status == PASSED)
  414.     /* Token is free, continue normal code */
  415. else
  416.     /* error condition */
  417.  
  418.  
  419.  
  420. EFFREEALL
  421. ---------
  422.  
  423. PURPOSE
  424. The effreeall function frees all expanded memory blocks, pages, and
  425. handles effreeallallocated by your application.  Effreeall is a convenient 
  426. function to use when you are ending your application.
  427.  
  428. **CAUTION** The expanded memory manager (MEMLIB) is NOT a part of DOS.
  429.             MEMLIB will not automatically free your allocated blocks when 
  430.             you exit your application.  Your application should free all 
  431.             blocks during any kind of exit, including <CTL><BREAK> or
  432.             other error conditions.
  433.  
  434. CALLING SEQUENCE
  435. unsigned int status;
  436. status = effreeall ( );
  437.  
  438. STATUS
  439. PASSED (zero)           All blocks, handles, and pages are now free.
  440. error (non-zero value)  See Appendix B for descriptions of error codes.
  441.  
  442. EXAMPLE
  443. #include "memlib.h"
  444. #include "errors.h"
  445.  
  446. unsigned int status;
  447.     ...
  448. status = effreeall();
  449. if (status == PASSED)
  450.     printf ("effreeall() successful");
  451. else
  452.     /* error condition */
  453.  
  454.  
  455.  
  456. EFMALLOC
  457. -------- 
  458.  
  459. PURPOSE
  460. The efmalloc function is analogous to the standard C function malloc.
  461. In the same way that malloc allocates conventional memory, the efmalloc
  462. function allocates a block of memory from expanded memory pool.  You can
  463. allocate up to 64K bytes with a call to efmalloc.
  464.  
  465. There is one significant difference between malloc and efmalloc.  A
  466. call to malloc allocates memory and returns a pointer, giving you access to
  467. that memory.  Efmalloc allocates memory, but doesn't return a pointer.
  468.  
  469. Here's why:  You can't access expanded memory the same way you access
  470. conventional memory.  You have to map a block of expanded memory into
  471. the page frame before you can access it.  Once you've mapped in a block,
  472. you get a pointer to that block.   With MEMLIB, you access a block using
  473. the seteptrs function (also set1eptr, set2eptrs, and set3eptrs).  See the
  474. seteptrs function for more information about accessing expanded memory.
  475.  
  476. **NOTE**  You must use the effree (or effreeall) function to free a block of
  477.           memory allocated with efmalloc.
  478.  
  479. CALLING SEQUENCE
  480. unsigned int status;
  481. status = efmalloc (size, &token);
  482.  
  483.      unsigned int  size       The size (in bytes) desired for the memory 
  484.                               block.  The size must be greater than zero.
  485.                               (input)
  486.      unsigned int  token      An identifier assigned to the memory block
  487.                               you've allocated.  The token identifies that 
  488.                               memory block in subsequent calls to other 
  489.                               functions such as set1eptr.  (output)
  490.  
  491. STATUS
  492. PASSED (zero)           The memory manager has allocated the block as
  493.                         expanded memory.
  494. error (non-zero value)  See Appendix B for descriptions of error
  495. codes.
  496.  
  497. EXAMPLE
  498. #include "memlib.h"
  499. #include "errors.h"
  500.  
  501. unsigned int size;
  502. unsigned int status;
  503. unsigned int token;
  504.  
  505. size = 100 * sizeof(int);
  506. status = efmalloc (size, &token);
  507. if (status == PASSED)
  508.     /* Continue normal code.  We have allocated */
  509.     /* space to store 100 integer values.        */
  510. else
  511.     /* error condition */
  512.  
  513.  
  514. EMEMAVL
  515. -------
  516.  
  517. PURPOSE
  518. The ememavl function computes the amount (in bytes) of expanded memory
  519. available in your computer.  The amount returned by ememavl is the total of
  520. all expanded memory available -- it is not the largest contiguous block of
  521. expanded memory (see ememmax).
  522.  
  523. CALLING SEQUENCE
  524. unsigned int status;
  525. status = ememavl (&size)
  526.      unsigned long  size      The amount of expanded memory (in bytes)
  527.                               ememavl returns (output)
  528.  
  529. STATUS
  530. PASSED (zero)           The memory manager has returned the total amount of 
  531.                         expanded memory.
  532.  
  533. error (non-zero value)  See Appendix B for descriptions of the error codes.
  534.  
  535. EXAMPLE
  536. #include "memlib.h"
  537. #include "errors.h"
  538.  
  539. unsigned int  status;
  540. unsigned long size;
  541.  
  542. status = ememavl (&size);
  543. if (status == PASSED)
  544.     printf ("Exp. memory avail. = %lu bytes \n",
  545.              size);
  546. else
  547.     /* error condition */
  548.  
  549.  
  550. EMEMMAX
  551. -------
  552.  
  553. PURPOSE
  554. The ememmax function returns the size (in bytes) of the largest usable
  555. ememmaxblock of expanded memory.  Because blocks of free memory can be 
  556. fragmented, this amount may be smaller than the total amount of free 
  557. expanded memory.
  558.  
  559. CALLING SEQUENCE
  560. unsigned int status;
  561. status = ememmax (&size);
  562.  
  563.      unsigned int  size  The number of bytes in the largest usable block of
  564.                          expanded memory.  (output)
  565.  
  566. STATUS
  567. PASSED (zero)           The memory manager has returned the size of the 
  568.                         largest usable block.
  569. error (non-zero value)  See Appendix B for descriptions of the error codes.
  570.  
  571. EXAMPLE
  572. #include "memlib.h"
  573. #include "errors.h"
  574.  
  575. unsigned int status;
  576. unsigned int size;
  577.  
  578. status = ememmax (&size);
  579. if (status == PASSED)
  580.     printf ("Largest block available = %u bytes \n",
  581.              size);
  582. else
  583.     /* error condition */
  584.  
  585.  
  586. EMSIZE
  587. ------
  588.  
  589. PURPOSE
  590. The emsize function computes the size of a previously allocated block
  591. of expanded memory.  Identify the block using the token that efmalloc
  592. returned emsizeafter allocating it.
  593.  
  594. CALLING SEQUENCE
  595. unsigned int status;
  596. status = emsize (token, &size);
  597.  
  598.      unsigned int  token      Identifier for the block. (input)
  599.      unsigned int  size       The size of the block (in bytes).  (output)
  600.  
  601. STATUS
  602. PASSED (zero)           The token was valid; the size is computed.
  603. error (non-zero value)  See Appendix B for descriptions of error
  604. codes.
  605.  
  606. EXAMPLE
  607. #include "memlib.h"
  608. #include "errors.h"
  609.  
  610. unsigned int status;
  611. unsigned int token;
  612. unsigned int size;
  613.  
  614. status = efmalloc (200, &token);
  615. if (status != PASSED)
  616.     /* error condition */
  617. else
  618.     /* continue normal code */
  619.     ...
  620. status = emsize (token, &size)
  621. if (status == PASSED)
  622.     printf ("Size of block = %u bytes \n", size);
  623. else
  624.     /* error condition */
  625.  
  626.  
  627. POP_CONTEXT
  628. -----------
  629.  
  630. PURPOSE
  631. The pop_context function restores the context saved by the
  632. push_context function.
  633.  
  634. **NOTE**  When you call pop_context, you lose access to the blocks that
  635.           were mapped in at the time of the call.
  636.  
  637. CALLING SEQUENCE
  638. unsigned int status;
  639. status = pop_context( );
  640.  
  641. STATUS
  642. PASSED (zero)           The context of block ( ) is restored.
  643. error (non-zero value)  See Appendix B for descriptions of error codes.
  644.  
  645. EXAMPLE
  646. #include "memlib.h"
  647. #include "errors.h"
  648.  
  649. unsigned int status;
  650. unsigned int token1;
  651. unsigned int token2;
  652. void         *pointer1;
  653. void         *pointer2;
  654.  
  655. status = efmalloc (100, &token1);
  656. if (status != PASSED)
  657.     /* error condition */
  658. else
  659.     /* continue normal code */
  660.    ...
  661. status = efmalloc (200, &token2);
  662. if (status != PASSED)
  663.     /* error condition */
  664. else
  665.     /* continue normal code */
  666.     ...
  667. status = set1eptr (token1, &pointer1);
  668. if (status != PASSED)
  669.     /* error condition */
  670. else
  671.     /* continue normal code */
  672.     ...
  673. status = push_context();
  674. if (status != PASSED)
  675.     /* error condition */
  676. else
  677.     /* save context for block 1 */
  678. status = set1eptr (token2, &pointer2);
  679. if (status != PASSED)
  680.     /* error condition */
  681. else
  682.     /* context for block 2 is active -- */
  683.     /* can't access block 1             */
  684.    ...
  685. status = pop_context();
  686. if (status != PASSED)
  687.     /* error condition */
  688. else
  689.     /* context for block 1 is active -- */
  690.     /* can't access block 2             */
  691.  
  692.  
  693. PUSH_CONTEXT
  694. ------------
  695.  
  696. PURPOSE
  697. The push_context function provides a convenient way to make the context of 
  698. a mapped block available for later use.  The context tells MEMLIB which 
  699. blocks are mapped into which physical pages. Push_context saves the 
  700. context, making it easy to restore access to whatever block(s) were mapped 
  701. in at the time of the call to push_context.
  702.  
  703. Restore the context you've "pushed" using the pop_context function
  704. (see Function 12).
  705.  
  706. CALLING SEQUENCE
  707. unsigned int status;
  708. status = push_context( );
  709.  
  710. STATUS
  711. PASSED (zero)           The memory manager has pushed the context of the 
  712.                         block onto a stack.
  713. error (non-zero value)  See Appendix B for descriptions of error codes.
  714.  
  715. **NOTE**  To save a context, MEMLIB needs to allocate a small amount of
  716.           conventional memory.  MEMLIB allocates this memory dynamically--
  717.           allocating just enough memory to save the context at the time of
  718.           the call (usually less than 20 bytes).
  719.  
  720. EXAMPLE
  721. #include "memlib.h"
  722. #include "errors.h"
  723.  
  724. unsigned int status;
  725. unsigned int token1;
  726. unsigned int token2;
  727. void         *pointer1;
  728. void         *pointer2;
  729.  
  730. status = efmalloc (100, &token1);
  731. if (status != PASSED)
  732.     /* error condition */
  733. else
  734.     /* continue normal code */
  735.     ...
  736. status = efmalloc (200, &token2);
  737. if (status != PASSED)
  738.     /* error condition */
  739. else
  740.     /* continue normal code */
  741.    ...
  742. status = set1eptr (token1, &pointer1);
  743.    ...
  744. if (status != PASSED)
  745.     /* error condition */
  746. else
  747.     /* continue normal code */
  748.     ...
  749. status = push_context();
  750. if (status != PASSED)
  751.     /* error condition */
  752. else
  753.     /* save context for block 1 */
  754.     ...
  755. status = set1eptr (token2, &pointer2);
  756. if (status != PASSED)
  757.     /* error condition */
  758. else
  759.     /* context for block 2 is active -- */
  760.     /* can't access block 1             */
  761.    ...
  762. status = pop_context();
  763. if (status != PASSED)
  764.     /* error condition */
  765. else
  766.     /* context for block 1 is active -- */
  767.     /* can't access block 2             */
  768.  
  769.  
  770. SETEPTRS
  771. --------
  772.  
  773. PURPOSE
  774. The seteptrs function attempts to gain access to the blocks you specify.  
  775. Seteptrs then returns pointers to those blocks. Use this function if you 
  776. need access to more than three blocks at once.   Use set1eptr, set2eptrs, 
  777. or set3eptrs to access 1, 2, or 3 blocks of memory.
  778.  
  779. You can access all allocated blocks, but not necessarily all at the same 
  780. time.  You can access only that memory which is mapped into the page frame.  
  781. Each expanded memory page is 16K, so if your page frame is 64K bytes, it 
  782. will hold four pages, and any four blocks of 16K or less can be mapped in 
  783. at one time.  (EMS page frames are guaranteed to be at least 64K bytes.)
  784.  
  785. If the combined size of all memory blocks you allocate during your 
  786. program's execution is less than the size of your page frame, you can 
  787. access all of the blocks at once.
  788.  
  789. For a more detailed description of page frames, read Chapter 1 in the EMS 
  790. manual.
  791.  
  792. **NOTE**  Seteptrs will unmap any pages that were mapped in before the call
  793. to seteptrs.  If you want to call seteptrs, but want to regain access to a 
  794. block that had been mapped in before the call, use the push_context 
  795. function (before you call seteptrs).  See push_context.
  796.  
  797. CALLING SEQUENCE
  798. unsigned int status;
  799. status = seteptrs (num_blocks, tokens, pointers);
  800.  
  801.        unsigned int num_blocks          The number of blocks you want to
  802.                                         access. (input)
  803.        unsigned int tokens[num_blocks]  An array of tokens that efmalloc
  804.                                         returned when it allocated the 
  805.                                         memory blocks.  (input)
  806.        void    *pointers[num_blocks]    The array of pointers seteptrs
  807.                                         returns.  Pointer[i] will point to 
  808.                                         the block of memory identified by 
  809.                                         token[i]. (output)
  810.  
  811. STATUS
  812. PASSED (zero)           You can gain access to all of the specified blocks.
  813. error (non-zero value)  See Appendix B for descriptions of error codes.
  814.  
  815. EXAMPLE
  816. #include "memlib.h"
  817. #include "errors.h"
  818.  
  819. unsigned int tokens[2];
  820.       /* Set array size for the number of blocks */
  821.       /* you wish to allocate (in this case, 2)  */
  822. void far     *pointers[2];
  823. unsigned int status;
  824.  
  825. status = efmalloc (200, &token[0]);
  826. if (status != PASSED)
  827.     /* error condition */
  828. else
  829.     /* continue normal code */
  830.     ...
  831. status = efmalloc (600, &token[1]);
  832. if (status != PASSED)
  833.     /* error condition */
  834. else
  835.     /* continue normal code */
  836.     ...
  837. status = seteptrs (2, tokens, pointers)
  838. if (status == PASSED)
  839.     /* blocks are mapped in -- use */
  840.     /* pointers to reference them  */
  841. else
  842.     /* error condition */
  843.  
  844.  
  845. SET1EPTR
  846. --------
  847.  
  848. PURPOSE
  849. The set1eptr function provides access to a single block of memory by 
  850. calling seteptrs.  (This is a convenience routine for programmers who don't 
  851. want to declare the arrays required by seteptrs.)
  852.  
  853. CALLING SEQUENCE
  854. unsigned int status;
  855. status = set1eptr (token, &pointer);
  856.  
  857.      unsigned int  token      The token that efmalloc returned when it
  858.                               allocated that block of memory. (input)
  859.      void          *pointer   The pointer that set1eptr returns to the 
  860.                               application. (output)
  861.  
  862. STATUS
  863. PASSED (zero)           You have access to the block.
  864. error (non-zero value)  See Appendix B for descriptions of error codes.
  865.  
  866. EXAMPLE
  867. #include "memlib.h"
  868. #include "errors.h"
  869.  
  870. void         *pointer;
  871. unsigned int token;
  872. unsigned int status;
  873.  
  874. status = efmalloc (500, &token);
  875. if (status != PASSED)
  876.     /* error condition */
  877. else
  878.     /* continue normal code */
  879.     ...
  880. status = set1eptr (token, &pointer);
  881. if (status == PASSED)
  882.     /* You have access to that block.  Use   */
  883.     /* the pointer as the block's reference. */
  884. else
  885.     /* error condition */
  886.  
  887.  
  888. SET2EPTRS
  889. ---------
  890.  
  891. PURPOSE
  892. The set2eptrs function provides access to two blocks of expanded memory by 
  893. calling seteptrs.  (This is a convenience routine for programmers who don't
  894. want to declare the arrays required by seteptrs.)
  895.  
  896. CALLING SEQUENCE
  897. unsigned int status;
  898. status = set2eptrs (token1, token2, &pointer1, &pointer2);
  899.  
  900.      unsigned int  token1     The token efmalloc returned when it allocated
  901.                               the first block of memory. (input)
  902.      unsigned int  token2     The token efmalloc returned when it allocated
  903.                               the second block of memory. (input)
  904.      void          *pointer1  The pointer to the first block that set2eptrs
  905.                               returns. (output)
  906.      void          *pointer2  The pointer to the second block that set2eptrs
  907.                               returns. (output)
  908.  
  909. STATUS
  910. PASSED (zero)           You have access to these two blocks.
  911. error (non-zero value)  See Appendix B for descriptions of error codes.
  912.  
  913. EXAMPLE
  914. #include "memlib.h"
  915. #include "errors.h"
  916.  
  917. void         *pointer1;
  918. void         *pointer2;
  919. unsigned int token1;
  920. unsigned int token2;
  921. unsigned int status;
  922.  
  923. status = efmalloc (500, &token1);
  924. if (status != PASSED)
  925.     /* error condition */
  926. else
  927.     /* continue normal code */
  928.     ...
  929. status = efmalloc (900, &token2);
  930. if (status != PASSED)
  931.     /* error condition */
  932. else
  933.     /* continue normal code */
  934.    ...
  935. status = set2eptrs (token1, token2, &pointer1, &pointer2);
  936. if (status == PASSED)
  937.     /* You have access to these blocks. */
  938.     /* Use the pointers as references.  */
  939. else
  940.     /* error condition */
  941.  
  942.  
  943. SET3EPTRS
  944. ---------
  945.  
  946. PURPOSE
  947. The set3eptrs function provides access to three blocks of expanded memory 
  948. by calling seteptrs.  (This is a convenience routine for programmers who 
  949. don't want to declare the arrays required by seteptrs.)
  950.  
  951. CALLING SEQUENCE
  952. unsigned int status;
  953. status = set3eptrs (token1, token2, token3, &pointer1, &pointer2, &pointer3);
  954.  
  955.      unsigned int  token1     The token efmalloc returned when it allocated
  956.                               the first block of memory. (input)
  957.      unsigned int  token2     The token efmalloc returned for the second 
  958.                               block. (input)
  959.      unsigned int  token3     The token efmalloc returned for the third 
  960.                               block. (input)
  961.      void          *pointer1  The pointer to the first block that set3eptrs 
  962.                               returns. (output)
  963.      void          *pointer2  The pointer to the second block that set3eptrs
  964.                               returns. (output)
  965.      void          *pointer3  The pointer to the third block. (output)
  966.  
  967. STATUS
  968. PASSED (zero)            You can gain access to these three blocks.
  969. error (non-zero value)   See Appendix B for descriptions of error codes.
  970.  
  971. EXAMPLE
  972. #include "memlib.h"
  973. #include "errors.h"
  974.  
  975. void         *pointer1;
  976. void         *pointer2;
  977. void         *pointer3;
  978. unsigned int token1;
  979. unsigned int token2;
  980. unsigned int token3;
  981. unsigned int status;
  982.  
  983. status = efmalloc (500, &tok1);
  984. if (status != PASSED)
  985.     /* error condition */
  986. else
  987.     /* continue normal code */
  988.     ...
  989. status = efmalloc (900, &tok2);
  990. if (status != PASSED)
  991.     /* error condition */
  992. else
  993.     /* continue normal code */
  994.    ...
  995. set3eptrs status = efmalloc (300, &tok3);
  996. if (status != PASSED)
  997.     /* error condition */
  998. else
  999.     /* continue normal code */
  1000.     ...
  1001. status = set3eptrs (token1, token2, token3,
  1002.                      &pointer1, &pointer2, &pointer3);
  1003. if (status == PASSED)
  1004.     /* Blocks are allocated; use pointers as references */
  1005. else
  1006.     /* error condition */
  1007.  
  1008.  
  1009.  
  1010.  
  1011. Chapter 3
  1012. EMMLIB:  LIBRARY FOR ASSEMBLY LANGUAGE
  1013.          AND C DEVELOPERS
  1014.  
  1015.  
  1016. EMMLIB is a collection of assembly language functions that call EMS 
  1017. functions directly. This library provides full EMS capability to C 
  1018. programmers; EMMLIB performs all of the functions listed in the 
  1019. Lotus-Intel-Microsoft Expanded Memory Specification.
  1020.  
  1021. If you want to use expanded memory for more complex uses such as named 
  1022. handles, alternate register sets, or page aliasing, then you will need the 
  1023. advanced functions available from EMMLIB.
  1024.  
  1025. **NOTE**  LIM-EMS is a powerful and complex specification.  The EMMLIB 
  1026. routines are designed to allow high level languages to use the full power 
  1027. of EMM directly; the routines are not designed to simplify the 
  1028. specification.
  1029.  
  1030.  
  1031. The LIM specification has approximately 30 functions, and most of these 
  1032. functions have subfunctions.  EMMLIB provides C-callable routines for all 
  1033. of the functions and subfunctions (a total of 59).  The EMMLIB functions 
  1034. are described in comment headers in the .ASM files on the Intel diskettes.  
  1035. Each filename includes the number of the EMS function corresponding to the 
  1036. EMMLIB function.
  1037.  
  1038. Table 3-1 is a list of the functions available in EMMLIB, grouped according 
  1039. to the operations they perform.  The table includes the name of the 
  1040. function, the file containing the code and description, and the 
  1041. corresponding function number from EMS.
  1042.  
  1043. Table 3-2 lists the functions in alphabetical order, and includes cross 
  1044. references to the filename and corresponding EMS function.
  1045.  
  1046. For a detailed description of a function, read the <Filename> file using 
  1047. any text editor, or read the description of the corresponding assembly 
  1048. language function <EMS Function No.> in the EMS manual.
  1049.  
  1050. For example, to map in a couple of pages of expanded memory, you could use 
  1051. the map_unmap_pages function.  To learn how to use this function, you would 
  1052. read either file EMMLIB23.ASM or the description of Function 17 in the EMS 
  1053. manual.
  1054.  
  1055. **NOTE**  EMMLIB.H is a header file that provides your C code with all of 
  1056. the "typedefs", function prototypes, and "#defines" that you need to call 
  1057. the EMMLIB functions.  Be sure to include this file when you use any EMMLIB 
  1058. function.
  1059.  
  1060.  
  1061. Table 3-1      EMMLIB Functions grouped by operation
  1062.  
  1063. ______________________________________________________________
  1064.  
  1065. Function Name                       Filename    EMS Function No.
  1066. _____________________________________________________________
  1067. presence, status, and version
  1068.   EMM_installed                   EMM01-B.ASM      1
  1069.   get_EMM_status                  EMM01-A.ASM      1
  1070.   get_EMM_version                 EMM07-A.ASM      7
  1071.  
  1072. memory allocation
  1073.   get_unalloc_page_count          EMM03-A.ASM      3
  1074.   get_alloc_page_count            EMM03-B.ASM      3
  1075.   get_total_page_count            EMM03-C.ASM      3
  1076.   alloc_pages                     EMM04-A.ASM      4
  1077.   dealloc_pages                   EMM06-A.ASM      6
  1078.   realloc_pages                   EMM18-A.ASM      18
  1079.   get_unalloc_raw_page_count      EMM26-A.ASM      26
  1080.   get_alloc_raw_page_count        EMM26-B.ASM      26
  1081.   get_total_raw_page_count        EMM26-C.ASM      26
  1082.   alloc_std_pages                 EMM27-A.ASM      27
  1083.   alloc_raw_pages                 EMM27-B.ASM      27
  1084.  
  1085. mappable memory region information
  1086.   get_page_frame_seg              EMM02-A.ASM      2
  1087.   get_mappable_conv_regions       EMM25-A.ASM      25
  1088.   get_mappable_exp_regions        EMM25-A.ASM      25
  1089.   get_mappable_regions            EMM25-A.ASM      25
  1090.   get_mappable_conv_region_count  EMM25-A.ASM      25
  1091.   get_mappable_exp_region_count   EMM25-A.ASM      25
  1092.   get_page_frame_count            EMM25-A.ASM      25
  1093.   get_mappable_region_count       EMM25-C.ASM      25
  1094.  
  1095. memory mapping
  1096.   map_unmap_page                  EMM05-A.ASM      5
  1097.   map_unmap_pages                 EMM17-A.ASM      17
  1098.  
  1099. memory mapping context
  1100.   save_context                    EMM08-A.ASM      8
  1101.   restore_context                 EMM09-A.ASM      9
  1102.   get_context                     EMM15-A.ASM      15
  1103.   set_context                     EMM15-B.ASM      15
  1104.   get_set_context                 EMM15-C.ASM      15
  1105.   get_context_size                EMM15-D.ASM      15
  1106.   get_partial_context             EMM16-A.ASM      16
  1107.   get_partial_context_size        EMM16-C.ASM      16
  1108.   set_partial_context             EMM16-B.ASM      16
  1109.  
  1110. memory movement and exchange
  1111.   move_memory_region              EMM24-A.ASM      24
  1112.   xchg_memory_region              EMM24-B.ASM      24
  1113.  
  1114. handle management
  1115.   get_handle_count                EMM12-A.ASM      12
  1116.   get_handle_pages                EMM13-A.ASM      13
  1117.   get_all_handles_pages           EMM14-A.ASM      14
  1118.   get_handle_attrib               EMM19-A.ASM      19
  1119.   set_handle_attrib               EMM19-B.ASM      19
  1120.   get_attrib_capability           EMM19-C.ASM      19
  1121.   get_handle_name                 EMM20-A.ASM      20
  1122.   set_handle_name                 EMM20-B.ASM      20
  1123.   get_handle_dir                  EMM21-A.ASM      21
  1124.   search_handle_name              EMM21-B.ASM      21 
  1125.   get_total_handles               EMM21-C.ASM      21
  1126.  
  1127. program flow control
  1128.   alter_map_jump                  EMM22-A.ASM      22
  1129.   alter_map_call                  EMM23-A.ASM      23
  1130.   get_alter_map_call_stack_size   EMM23-B.ASM      23
  1131.  
  1132. Operating System only
  1133.   enable_OS_fcns                  EMM30-A.ASM      30
  1134.   disable_OS_fcns                 EMM30-B.ASM      30
  1135.   return_OS_access_key            EMM30-C.ASM      30
  1136.   get_hw_info                     EMM26-D.ASM      26
  1137.   get_alt_reg_set                 EMM28-A.ASM      28
  1138.   set_alt_reg_set                 EMM28-B.ASM      28
  1139.   get_alt_context_size            EMM28-C.ASM      28
  1140.   alloc_alt_reg_set               EMM28-D.ASM      28
  1141.   dealloc_alt_reg_set             EMM28-E.ASM      28
  1142.   alloc_DMA_reg_set               EMM28-F.ASM      28
  1143.   enable_DMA_reg_set              EMM28-G.ASM      28
  1144.   disable_DMA_reg_set             EMM28-H.ASM      28
  1145.   dealloc_DMA_reg_set             EMM28-I.ASM      28
  1146.   prep_EMM_warmboot               EMM29-A.ASM      29
  1147.   _____________________________________________
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153. Table 3-2 EMMLIB Functions in alphabetical order
  1154. ________________________________________________________________
  1155.  
  1156. Function Name                        Filename    EMS Function No.
  1157. _________________________________________________________________
  1158.  
  1159. alloc_alt_reg_set                    EMM28-D.ASM      28
  1160. alloc_DMA_reg_set                    EMM28-F.ASM      28
  1161. alloc_pages                          EMM04-A.ASM      4
  1162. alloc_std_pages                      EMM27-A.ASM      27
  1163. alloc_raw_pages                      EMM27-B.ASM      27
  1164. alter_map_jump                       EMM22-A.ASM      22
  1165. alter_map_call                       EMM23-A.ASM      23
  1166.  
  1167. dealloc_alt_reg_set                  EMM28-E.ASM      28
  1168. dealloc_DMA_reg_set                  EMM28-I.ASM      28
  1169. dealloc_pages                        EMM06-A.ASM      6
  1170. disable_DMA_reg_set                  EMM28-H.ASM      28
  1171. disable_OS_fcns                      EMM30-B.ASM      30
  1172.  
  1173. EMM_installed                        EMM01-B.ASM      1
  1174. enable_DMA_reg_set                   EMM28-G.ASM      28
  1175. enable_OS_fcns                       EMM30-A.ASM      30
  1176.  
  1177. get_all_handles_pages                EMM14-A.ASM      14
  1178. get_alloc_page_count                 EMM03-B.ASM      3
  1179. get_alloc_raw_page_count             EMM26-B.ASM      26
  1180. get_alt_context_size                 EMM28-C.ASM      28
  1181. get_alter_map_call_stack_size        EMM23-B.ASM      23
  1182. get_alt_reg_set                      EMM28-A.ASM      28
  1183. get_attrib_capability                EMM19-C.ASM      19
  1184.  
  1185. get_context                          EMM15-A.ASM      15
  1186. get_context_size                     EMM15-D.ASM      15
  1187. get_EMM_status                       EMM01-A.ASM      1
  1188. get_EMM_version                      EMM07-A.ASM      7
  1189. get_handle_count                     EMM12-A.ASM      12
  1190. get_handle_pages                     EMM13-A.ASM      13
  1191. get_handle_attrib                    EMM19-A.ASM      19
  1192. get_handle_name                      EMM20-A.ASM      20
  1193. get_handle_dir                       EMM21-A.ASM      21
  1194. get_hw_info                          EMM26-D.ASM      26
  1195.  
  1196. get_mappable_conv_regions            EMM25-A.ASM      25
  1197. get_mappable_conv_region_count       EMM25-A.ASM      25
  1198. get_mappable_exp_regions             EMM25-A.ASM      25
  1199. get_mappable_exp_region_count        EMM25-A.ASM      25
  1200. get_mappable_regions                 EMM25-B.ASM      25
  1201. get_mappable_region_count            EMM25-C.ASM      25
  1202. get_page_frame_count                 EMM25-A.ASM      25
  1203. get_page_frame_seg                   EMM02-A.ASM      2
  1204.  
  1205. get_partial_context                  EMM16-A.ASM      16
  1206. get_partial_context_size             EMM16-C.ASM      16
  1207. get_set_context                      EMM15-C.ASM      15
  1208. get_total_handles                    EMM21-C.ASM      21
  1209. get_total_page_count                 EMM03-C.ASM      3
  1210. get_total_raw_page_count             EMM26-C.ASM      26
  1211. get_unalloc_page_count               EMM03-A.ASM      3
  1212. get_unalloc_raw_page_count           EMM26-A.ASM      26
  1213.  
  1214. map_unmap_page                       EMM05-A.ASM      5
  1215. map_unmap_pages                      EMM17-A.ASM      17
  1216. move_memory_region                   EMM24-A.ASM      24
  1217.  
  1218. prep_EMM_warmboot                    EMM29-A.ASM      29
  1219.  
  1220. realloc_pages                        EMM18-A.ASM      18
  1221. restore_context                      EMM09-A.ASM      9
  1222. return_OS_access_key                 EMM30-C.ASM      30
  1223.  
  1224. save_context                         EMM08-A.ASM      8
  1225. search_handle_name                   EMM21-B.ASM      21
  1226. set_alt_reg_set                      EMM28-B.ASM      28
  1227. set_context                          EMM15-B.ASM      15
  1228. set_handle_attrib                    EMM19-B.ASM      19
  1229. set_handle_name                      EMM20-B.ASM      20
  1230. set_partial_context                  EMM16-B.ASM      16
  1231.  
  1232. xchg_memory_region                   EMM24-B.ASM      24
  1233. _________________________________________________________
  1234.  
  1235.  
  1236.  
  1237.  
  1238. Appendix A
  1239. EXAMPLE PROGRAM
  1240.  
  1241. /* The intent of this example program is to show how to store and         */
  1242. /* manipulate data in expanded memory using the C Memory Manager --       */
  1243. /* MEMLIB.                                                                */
  1244. /*                                                                        */
  1245. /* This example shows what developers need to do in order to manipulate   */
  1246. /* expanded memory in their own applications by using MEMLIB routines.    */
  1247. /* For a more detailed program that uses a doubly linked list data        */
  1248. /* structure, see the ROLODEX.C program.                                  */
  1249. /*                                                                        */
  1250. /* This program follows a seven-step algorithm:                           */
  1251. /*   1.  Check the total amount of expanded memory available.             */
  1252. /*   2.  Find the largest contiguous block of free expanded memory.       */
  1253. /*   3.  Allocate expanded memory for two strings.                        */
  1254. /*   4.  Calculate the size of the block allocated for the first string.  */
  1255. /*   5.  Print the two strings.                                           */
  1256. /*   6.  Manipulate the data by appending one string to the other.        */
  1257. /*   7.  Print the new string.                                            */
  1258. /**************************************************************************/
  1259.  
  1260. #include <stdio.h>
  1261. #include <string.h>
  1262.  
  1263. /**************************************************************************/
  1264. /* The two header files below contain the function prototypes for         */
  1265. /* MEMLIB routines and the error messages specific to MEMLIB.  Keep in    */
  1266. /* mind that MEMLIB calls EMMLIB functions, so you may get an error code  */
  1267. /* relating to EMS.  (EMS codes are explained in Table A-2 in the         */
  1268. /* EMS manual.)  You must include these two headers for any application   */
  1269. /* that will use MEMLIB.  If you are going to use any EMMLIB calls        */
  1270. /* directly, you must also include "emmlib.h."                            */
  1271. /**************************************************************************/
  1272.  
  1273. #include "memlib.h"
  1274. #include "errors.h"
  1275. #define PASSED          0           /* If the MEMLIB call was successful */
  1276.                                     /* it will return a zero.            */
  1277. #define MAX_STRING_SIZE 255
  1278. void abort (unsigned short);        /* If we encounter any errors, we    */
  1279.                                     /* call this function to "clean up." */
  1280. void main()
  1281. {
  1282.    unsigned short status;           /* The status after a MEMLIB call.   */
  1283.    char           *string1;         /* Our first data item.              */
  1284.    char           *string2;         /* Our second data item.             */
  1285.    unsigned int   token1;           /* The identifier to our first       */
  1286.                                     /* block of expanded memory.         */
  1287.    unsigned int   token2;           /* The identifier to our second      */
  1288.                                     /* block of expanded memory.         */
  1289.    unsigned int   max_block_size;   /* The size of the largest           */
  1290.                                     /* allocatable contiguous block.     */
  1291.    unsigned int   size;             /* The size of one of our blocks.    */
  1292.    unsigned long  max_exp_mem;      /* The amount of expanded mem avail. */
  1293.  
  1294.    /***********************************************/
  1295.    /* See how much total expanded memory we have. */
  1296.    /***********************************************/
  1297.  
  1298.    status = ememavl (&max_exp_mem);
  1299.    if (status != PASSED)
  1300.    {
  1301.      printf ("Unable to obtain total expanded memory size.\n");
  1302.      abort (status);
  1303.    }
  1304.    else
  1305.      printf ("Total expanded memory available: %lu\n", max_exp_mem);
  1306.  
  1307.    /*************************************************/
  1308.    /* Get the size of the largest contiguous block. */
  1309.    /*************************************************/
  1310.  
  1311.    status = ememmax (&max_block_size);
  1312.    if (status != PASSED)
  1313.    {
  1314.      printf ("Unable to obtain the largest contiguous block.\n");
  1315.      abort (status);
  1316.    }
  1317.    else
  1318.      printf ("Largest contiguous block: %u\n\n", max_block_size);
  1319.  
  1320.    /*********************************************/
  1321.    /* Allocate the memory and check for errors. */
  1322.    /*********************************************/
  1323.  
  1324.    status = efmalloc (MAX_STRING_SIZE, &token1);
  1325.    if (status != PASSED)
  1326.    {
  1327.      printf ("Unable to allocate first block.\n");
  1328.      abort (status);
  1329.    }
  1330.    else
  1331.      printf ("Allocated space for the first block.\n");
  1332.  
  1333.    status = efmalloc (MAX_STRING_SIZE, &token2);
  1334.    if (status != PASSED)
  1335.    {
  1336.      printf ("Unable to allocate second block.\n");
  1337.      abort (status);
  1338.  
  1339.    else
  1340.      printf ("Allocated space for the second block.\n\n");
  1341.  
  1342.    /********************************/
  1343.    /* Check the size of block one. */
  1344.    /********************************/
  1345.  
  1346.    status = emsize (token1, &size);
  1347.    if (status != PASSED)
  1348.    {
  1349.      printf ("Unable to obtain size for block %u\n", token1);
  1350.      abort (status);
  1351.    }
  1352.    else
  1353.      printf ("Size of block %u is %u\n\n", token1, size);
  1354.  
  1355.    /***********************************************/
  1356.    /* Map in the two blocks, checking for errors. */
  1357.    /***********************************************/
  1358.  
  1359.    status = set2eptrs (token1, token2, & (char *) string1, & (char *)string2);
  1360.    if (status != PASSED)
  1361.    {
  1362.      printf ("Unable to map in the two blocks.\n");
  1363.      abort (status);
  1364.    }
  1365.    else
  1366.      printf ("Blocks mapped in.\n\n");
  1367.  
  1368.     printf ("Putting data in expanded memory.\n\n");
  1369.  
  1370.    /*********************************************/
  1371.    /* Store values in expanded memory using the */
  1372.    /* pointers given to us from set2eptrs().    */
  1373.    /*********************************************/
  1374.  
  1375.    strcpy (string1, "'What if life is an illusion and nothing exists?'");
  1376.    strcpy (string2, "'In that case, I definitely overpaid for my carpet.' 
  1377.                       --Woody Allen");
  1378.  
  1379.    printf ("String1: %s\n", string1);
  1380.    printf ("String2: %s\n\n", string2);
  1381.  
  1382.    /**************************************************/
  1383.    /* Still using the pointers, manipulate the data. */
  1384.    /**************************************************/
  1385.  
  1386.    printf ("Manipulating data in expanded memory.\n");
  1387.  
  1388.    strcat (string1, string2);
  1389.  
  1390.    printf ("String1: %s\n\n", string1);
  1391.  
  1392.    /**************************************************************/
  1393.    /* Free all expanded memory we've allocated.  If effreeall()  */
  1394.    /* is unsuccessful, we don't want to call abort() because     */
  1395.    /* abort() would just call effreeall() again.                 */
  1396.    /**************************************************************/
  1397.  
  1398.    status = effreeall();
  1399.    if (status != PASSED)
  1400.    {
  1401.      printf ("Unable to free memory.\n");
  1402.      printf ("ERROR %X\n", status);
  1403.      exit (2);
  1404.    }
  1405.    else
  1406.      printf ("Expanded memory freed.\n");
  1407. }
  1408.  
  1409. /****************************************************************************/
  1410. /* Aborts the program with an error message.  Effreeall() frees all         */
  1411. /* pages, blocks, and handles associated with this application.  It is      */
  1412. /* imperative that you release all the expanded memory you've allocated     */
  1413. /* before exiting, so that other applications can use this memory.  If      */
  1414. /* you don't, you'll have to reboot to recover the lost memory.  Notice     */
  1415. /* also that a call to effreeall() checks the EMM status.  In case that     */
  1416. /* call fails,  you'll get an error condtion back to let you know the       */
  1417. /* memory was not freed.                                                    */
  1418. /*                                                                          */
  1419. /* You should always call effreeall() before aborting your program, even    */
  1420. /* if you get an error before allocating any memory.  Effreeall() will free */
  1421. /* the handles and memory that MEMLIB allocated when it was initialized.    */
  1422. /****************************************************************************/
  1423.  
  1424. void abort (status)
  1425. unsigned short status;
  1426. {
  1427.    printf ("ERROR %X\n", status);
  1428.    status = effreeall();
  1429.    if (status != PASSED)
  1430.    {
  1431.       printf ("ERROR %X from effreeall().\n");
  1432.       printf ("Expanded memory not freed.\n");
  1433.    }
  1434. exit (1);
  1435. }
  1436.  
  1437.  
  1438.  
  1439.  
  1440. Appendix B
  1441. MEMLIB ERROR MESSAGES
  1442.  
  1443. This appendix lists the MEMLIB error codes that may appear when you are 
  1444. running your application.  The codes are listed in numerical order.  Each 
  1445. error code description includes:
  1446.  o   the hexadecimal number of the error code
  1447.  o   a one-line description of the error
  1448.  o   a short explanation of why the error message appeared
  1449.  o   what you should do to correct the error
  1450.  
  1451. Because MEMLIB makes calls to EMMLIB functions, you may see messages other 
  1452. than those listed here.  Each EMMLIB error message includes a hexadecimal 
  1453. code number used by the Expanded Memory Specification (EMS).  To find out 
  1454. more about these errors, look up the code number in Table A-2, "Status and 
  1455. Function Code Cross Reference," in the EMS manual.
  1456.  
  1457. Error:
  1458.  
  1459.     0xD0     INVALID_TOKEN
  1460.  
  1461. cause        The token that the MEMLIB routine received did not represent
  1462.              an allocated block of memory.
  1463.  
  1464. action       Each time efmalloc allocates a block of memory, it returns a 
  1465.              token unique to that block.  Use this token when referring to
  1466.              a particular block.
  1467.  
  1468.  
  1469.      0xD1     NOT_ENOUGH_UNALLOCATED_PAGES
  1470.  
  1471. cause        Your computer does not have enough free expanded memory.  
  1472.              MEMLIB requires at least 1 page (16K bytes) for its internal 
  1473.              directory, and assumes that you'll need at least 1 more page 
  1474.              to store data for your application.
  1475.  
  1476. action       You need more expanded memory.  Add more memory to your Above
  1477.              Board, buy a Piggyback Option, or buy another Above Board.
  1478.  
  1479.  
  1480.      0xD2     TOO_MANY_DIRECTORY_ENTRIES
  1481.  
  1482. cause        You requested more separate blocks of memory than the MEMLIB
  1483.              directory can handle.  The maximum number of directory 
  1484.              entries available is 65535.
  1485.  
  1486. action       Try requesting a few larger blocks instead of many small blocks.
  1487.  
  1488.      0xD3     REQUEST_FOR_ZERO_LENGTH_BLOCK
  1489.  
  1490. cause        You tried to allocate a 0K-byte block of memory.
  1491.  
  1492. action       When you use efmalloc, make sure the size parameter is greater
  1493.              than zero.
  1494.  
  1495.      0xD4     CANNOT_MAP_ALL_BLOCKS
  1496.  
  1497. cause        The blocks you attempted to access can't all be mapped into the 
  1498.              page frame at the same time.
  1499.  
  1500. action       Try accessing fewer blocks at a time.  See the NOTE at the 
  1501.              beginning of the seteptrs function for more information on 
  1502.              the number of memory blocks you can access.
  1503.  
  1504.      0xD5     MAX_PUSH_CONTEXTS_EXCEEDED
  1505.  
  1506. cause        MEMLIB has a set maximum number of contexts it will "push" 
  1507.              onto a stack, and you have exceeded that maximum.  
  1508.              (See Function 11 for more information about contexts.)
  1509.  
  1510. action       You can either pop some of the contexts before pushing any 
  1511.              more, or you can change the maximum default.  In the 
  1512.              MEMINTRL.C file you'll find a #define called 
  1513.              MAX_CONTEXTS_AVAILABLE.  Increase this number, then recompile
  1514.              MEMLIB.
  1515.  
  1516.       0xD6     MALLOC_FAILURE
  1517.  
  1518. cause        When you tried to push a context, MEMLIB could not find enough
  1519.              open conventional memory to hold the context.
  1520.  
  1521. action       Use the pop_context function to release the contexts you have 
  1522.              already pushed.  
  1523.              If you haven't called push_context previously but get this 
  1524.              error, you don't have enough free conventional memory to use 
  1525.              the push_context function.  Unless you can free some of your
  1526.              computer's conventional memory, don't call push_context or
  1527.              pop_context.
  1528.  
  1529.  
  1530.        0xD7     NO_CONTEXT_AVAILABLE_TO_POP
  1531.  
  1532. cause        You attempted to call pop_context before calling push_context,
  1533.              or you tried to pop a context you had popped already.
  1534.  
  1535. action       Use the push_context function before using pop_context.
  1536.  
  1537.  
  1538.        0xD8     ERROR_REALLOCATING_PAGES
  1539.  
  1540. cause        Efmalloc could not allocate the block of memory you requested 
  1541.              because your computer doesn't have enough free expanded memory.
  1542.  
  1543. action       Allocate a smaller block of memory, add more memory to your 
  1544.              Above Board, or buy another.
  1545.  
  1546.  
  1547.         0xD9     NOT_INITIALIZED
  1548.  
  1549. cause        You called a function that was designed to be called by another
  1550.              function, not by your application.
  1551.  
  1552. action       Limit your MEMLIB function calls to the functions listed in 
  1553.              this manual.
  1554.  
  1555.  
  1556.  
  1557. Appendix C
  1558. TECHNICAL INFORMATION ABOUT MEMLIB
  1559.  
  1560. This appendix explains in detail how MEMLIB provides access to expanded 
  1561. memory, how it keeps track of expanded memory, how it allocates memory, and 
  1562. the algorithms it uses.  You don't need this information to use MEMLIB with 
  1563. your application program. It's provided for your information only.
  1564.  
  1565. If you'd like more information about how expanded memory works, read 
  1566. Chapter 1 in the EMS manual.
  1567.  
  1568.  
  1569. How MEMLIB provides access to expanded memory
  1570. ---------------------------------------------
  1571.  
  1572. You can have up to 32M bytes of expanded memory in your computer, and 
  1573. MEMLIB can provide access to all of it.
  1574.  
  1575. Expanded memory is divided into logical pages.  Each logical page is 16K 
  1576. bytes.
  1577.  
  1578. To access a block of expanded memory, MEMLIB needs to map in the logical 
  1579. page that the block uses.  MEMLIB can map only a limited number of these 
  1580. pages into the EMS page frame at one time.
  1581.  
  1582. For example, if your page frame is 64K bytes, four logical pages can be 
  1583. mapped into it.  You can access four memory blocks at the same time if the 
  1584. size of each block is 16K bytes or less.  However, accessing five blocks at 
  1585. once may be impossible, because the blocks might use five different logical 
  1586. pages (five pages won't fit in the page frame).
  1587.  
  1588. How MEMLIB keeps track of expanded memory
  1589. -----------------------------------------
  1590.  
  1591. The expanded memory manager, MEMLIB, is based on a directory structure.  
  1592. Each directory entry consists of four fields:
  1593.  
  1594.    unsigned int     token    (0xFFFF = free, otherwise = allocated)
  1595.    unsigned int     size     (size [in bytes] of this block)
  1596.    unsigned short  offset    (the offset into the first logical page of 
  1597.                              this block)
  1598.    int     logical_page[4]   (pages used)
  1599.  
  1600. Blocks less than or equal to 16K bytes will use one logical page; 16 - 32K, 
  1601. two pages; 32 - 48K, three pages; and 48 - 64K, four pages.
  1602.  
  1603. This directory is stored in expanded memory that MEMLIB allocates when 
  1604. needed.
  1605.  
  1606.  
  1607. How MEMLIB allocates expanded memory
  1608. ------------------------------------
  1609.  
  1610. To allocate memory, MEMLIB attempts to reuse as much deallocated memory as 
  1611. possible before allocating any new blocks.
  1612.  
  1613. When a block of memory is freed, MEMLIB checks all other freed blocks to 
  1614. see if they fall immediately before or after that block.  If there are any 
  1615. adjacent free blocks, MEMLIB combines the blocks into one larger block.  
  1616. When a user requests a block of memory, MEMLIB checks all free blocks and 
  1617. gives the user the smallest free block bigger than the size requested (best 
  1618. fit).  Any leftover memory is put into another free block.
  1619.  
  1620. EXAMPLE:
  1621.        A user makes an efmalloc request for a 6K block.  MEMLIB allocates 
  1622.        logical page 1 from EMM, and creates two directory entries:  one to 
  1623.        the 6K block and one to the 10K free block.
  1624.  
  1625.        Next, the user makes another efmalloc request, this time for an 11K 
  1626.        block.  11K won't fit in the 10K free block in logical page 1, and 
  1627.        will overlap into the next logical page if assigned to page 1 at all.  
  1628.        MEMLIB allocates an entirely new logical page, page 2. Again, it 
  1629.        creates one directory entry to point to the allocated block, and 
  1630.        another entry to point to the 5K of free memory (4).
  1631.  
  1632.  
  1633.  
  1634. Algorithms
  1635. ----------
  1636.  
  1637. When a user requests a block of memory (efmalloc), Intel uses the following
  1638. algorithm:
  1639.  
  1640.            (C pseudo code)
  1641.  
  1642. do
  1643.     if (exact fit)
  1644.         allocate block
  1645.     else
  1646.         check for best fit
  1647. while ((not exact fit) and (not last directory entry))
  1648. if (not exact fit)
  1649.     if (best fit)
  1650.         allocate block
  1651.         set directory entry for remainder
  1652.     else
  1653.         request page from expanded memory manager
  1654.         if request = OK
  1655.              allocate block
  1656.         else
  1657.              return NOT_ENOUGH_UNALLOCATED_PAGES error
  1658.  
  1659.  
  1660. To free a block of memory (effree), we use this algorithm:
  1661.  
  1662. do
  1663.     if (contiguous free block)
  1664.         combine into one free block
  1665. while (not last directory entry)
  1666.     if (no allocated pages found)
  1667.         deallocate all pages      /* prepare for program termination */
  1668.  
  1669.  
  1670. When mapping in blocks of memory (seteptrs), we use the following algorithm:
  1671.  
  1672. for (i = 0, i < number of requested blocks; i++)
  1673.     if (logical pages needed for block i are already mapped)
  1674.         OK = true
  1675.     else
  1676.         if (pages need for block i will fit)
  1677.              OK = true
  1678.              map in pages needed
  1679.         else
  1680.              return CANNOT_MAP_ALL_BLOCKS error
  1681.  
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.